﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using YasharEl.Infrastructure.ObjectFactory;
using System.Configuration;
using YasharEl.Infrastructure.ApplicationModel.Bootstrap;
using YasharEl.Infrastructure.ApplicationModel.Bootstrap.Extensibility;
using YasharEl.Infrastructure.ApplicationModel.Modularity.Bootstrap;

namespace YasharEl.Infrastructure.ApplicationModel.Modularity
{
    public abstract class BaseModule : IModule
    {
        #region Protected Fields

        private string _moduleName = "BaseModule";

        public System.Configuration.Configuration ModuleConfiguration
        {
            get;
            private set;
        }

        protected BaseDependencyContainer ModuleContainer
        {
            get;
            private set;
        }

        private BaseModuleBootstrapper<IModuleComponentBootstrappingExtension> ModuleBootstrapper
        {
            get;
            set;
        }

        #endregion

        #region IModule Members

        public void Initialize(BaseDependencyContainer container, string moduleName, string configFile)
        {
            ModuleContainer = container;
            _moduleName = moduleName;

            ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
            configMap.ExeConfigFilename = configFile;
            ModuleConfiguration = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
            ModuleBootstrapper = CreateModuleBootstrapper();
            if (ModuleBootstrapper == null)
            {
                throw new InvalidModularityConfigurationException("Module bootstrapper could not be resolved.");
            }

            AbstractBootstrappingStrategy<IModuleComponentBootstrappingExtension> complexStrategy = new ComplexModuleBootstrappingStrategy();

            ModuleBootstrapper.Initialize(complexStrategy);

            foreach (IModuleComponentBootstrappingExtension moduleComponent in EnumerateModuleComponents())
            {
                moduleComponent.ModuleConfiguration = ModuleConfiguration;
                moduleComponent.ModuleName = ModuleName;
                ModuleBootstrapper.AddExtension(moduleComponent);
            }
        }

        public void Run()
        {
            ModuleBootstrapper.Run();
        }

        public void Shutdown()
        {
            ModuleBootstrapper.Shutdown();
        }

        public virtual string ModuleName
        {
            get
            {
                return _moduleName;
            }
        }

        #endregion

        #region Abstract Methods

        protected abstract BaseModuleBootstrapper<IModuleComponentBootstrappingExtension> CreateModuleBootstrapper();

        protected abstract IEnumerable<IComplexBootstrappingExtension> EnumerateModuleComponents();

        #endregion
    }
}
